/*
 * Copyright (C) 2009 LianHaidong <lianhaidong@gmail.com>
 */

#ifndef _DFA_H
#define _DFA_H

#include "utils/list.h"

struct dfa_state;
struct dfa;
struct dfa_state_shift;

typedef int (*dfa_shift_func)(struct dfa_state_shift *shift, const char *cmd, void *arg);


struct dfa_state_shift {
	char *cmd;
	struct dfa_state *state;
	struct dfa_state *shift_state;
	struct list_head link;
	dfa_shift_func match;
	void *priv;
};

struct dfa_state {
	char *name;
	struct dfa *dfa;
	int shift_count;
	struct list_head shift_head;
	struct list_head link;
};

struct dfa {
	char *name;
	struct dfa_state start_state;
	int state_count;
	struct list_head link;
	struct list_head state_head;
	struct list_head obj_head;
};

struct dfa_object {
	char *name;
	struct dfa *dfa;
	struct dfa_state *current_state;
	struct list_head link;
};

extern struct dfa *dfa_create(char *name);

extern void dfa_delete(struct dfa *dfa);

extern struct dfa_object *dfa_new_object(struct dfa *dfa, char *name);

extern int dfa_del_object(struct dfa *dfa, struct dfa_object *obj);

extern int dfa_add_rule(struct dfa *dfa, char *src_name, char *cmd, char *dst_name, 
			dfa_shift_func match);

static inline char *__dfa_object_current_state_name(struct dfa_object *obj)
{
	return obj->current_state->name;
}

static inline char *dfa_object_current_state_name(struct dfa_object *obj)
{
	if (obj && obj->current_state)
		return __dfa_object_current_state_name(obj);

	return NULL;
}

extern int dfa_add_state(struct dfa *dfa, char *state_name);

extern int dfa_reset(struct dfa *dfa);

extern int dfa_object_put_cmd(struct dfa_object *obj, const char *cmd, void *arg);

#endif	/* _DFA_H */
